package com.example.urmsadmin.Util;

import com.example.urmsadmin.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class ExcelInsert {

// private static Logger logger = Logger.getLogger(ExcelReader.class.getName()); // 日志打印类

    private static final String XLS = "xls";
    private static final String XLSX = "xlsx";

    /**
     * 根据文件后缀名类型获取对应的工作簿对象
     * @param inputStream 读取文件的输入流
     * @param fileType 文件后缀名类型（xls或xlsx）
     * @return 包含文件数据的工作簿对象
     * @throws IOException
     */
    public static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {
        Workbook workbook = null;
        if (fileType.equalsIgnoreCase(XLS)) {
            workbook = new HSSFWorkbook(inputStream);
        } else if (fileType.equalsIgnoreCase(XLSX)) {
            workbook = new XSSFWorkbook(inputStream);
        }
        return workbook;
    }

    /**
     * 读取Excel文件内容
     * @param myfile 要读取的Excel文件流
     * @return 读取结果列表，读取失败时返回null
     */
    public static List<SysUser> readExcel(MultipartFile myfile) {

        Workbook workbook = null;
        FileInputStream inputStream = null;

        try {
            // 获取Excel后缀名
            String fileName=myfile.getOriginalFilename();
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());

            File file = new File(myfile.getOriginalFilename());
            FileUtils.copyInputStreamToFile(myfile.getInputStream(), file);
            // 获取Excel工作簿
            inputStream = new FileInputStream(file);
            workbook = getWorkbook(inputStream, fileType);
            // 会在本地产生临时文件，用完后需要删除
            if (file.exists()) {
                file.delete();
            }

            // 读取excel中的数据
            List<SysUser> resultDataList = parseExcel(workbook);

            return resultDataList;
        } catch (Exception e) {
            return null;
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                // logger.warning("关闭数据流出错！错误信息：" + e.getMessage());
                return null;
            }
        }
    }

    /**
     * 解析Excel数据
     * @param workbook Excel工作簿对象
     * @return 解析结果
     */
    private static List<SysUser> parseExcel(Workbook workbook) {
        List<SysUser> resultDataList = new ArrayList<>();
        // 解析sheet
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
            Sheet sheet = workbook.getSheetAt(sheetNum);

            // 校验sheet是否合法
            if (sheet == null) {
                log.error("获取Sheet对象失败！");
                continue;
            }

            // 获取第一行数据
            int firstRowNum = sheet.getFirstRowNum();
            Row firstRow = sheet.getRow(firstRowNum);
            if (null == firstRow) {
                log.error("解析Excel失败，在第一行没有读取到任何数据！");
            }

            // 解析每一行的数据，构造数据对象
            int rowStart = firstRowNum + 1;
            int rowEnd = sheet.getPhysicalNumberOfRows();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
                Row row = sheet.getRow(rowNum);

                if (null == row) {
                    log.error("获取第"+rowNum+1+"行数据失败！");
                    continue;
                }

                SysUser resultData = convertRowToData(row);
                if (null == resultData) {
                    log.error("第 " + row.getRowNum() + "行数据不合法，已忽略！");
                    continue;
                }
                resultDataList.add(resultData);
            }
        }

        return resultDataList;
    }

    /**
     * 将单元格内容转换为字符串
     * @param cell
     * @return
     */
    private static String convertCellValueToString(Cell cell) {
        if(cell==null){
            return null;
        }
        String returnValue = null;
        switch (cell.getCellType()) {
            case NUMERIC: //数字
                if (HSSFDateUtil.isCellDateFormatted(cell)) {   // 处理日期格式、时间格式
                    SimpleDateFormat sdf = null;
                    if (cell.getCellStyle().getDataFormat() == HSSFDataFormat
                            .getBuiltinFormat("h:mm")) {
                        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    } else {// 日期
                        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    }
                    Date date = cell.getDateCellValue();
                    returnValue = sdf.format(date);
                } else if (cell.getCellStyle().getDataFormat() == 58) {
                    // 处理自定义日期格式：m月d日(通过判断单元格的格式id解决，id的值是58)
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
                    double value = cell.getNumericCellValue();
                    Date date = org.apache.poi.ss.usermodel.DateUtil
                            .getJavaDate(value);
                    returnValue = sdf.format(date);
                } else {
                    double value = cell.getNumericCellValue();
                    CellStyle style = cell.getCellStyle();
                    DecimalFormat format = new DecimalFormat();
                    String temp = style.getDataFormatString();
                    // 单元格设置成常规
                    if (temp.equals("General")) {
                        format.applyPattern("#");
                    }
                    returnValue = format.format(value);
                }
                break;
            case STRING: //字符串
                returnValue = cell.getStringCellValue();
                break;
            case BOOLEAN: //布尔
                Boolean booleanValue = cell.getBooleanCellValue();
                returnValue = booleanValue.toString();
                break;
            case BLANK: // 空值
                break;
            case FORMULA: // 公式
                returnValue = cell.getCellFormula();
                break;
            case ERROR: // 故障
                break;
            default:
                break;
        }
        return returnValue;
    }

    /**
     * 提取每一行中需要的数据，构造成为一个结果数据对象
     *
     * 当该行中有单元格的数据为空或不合法时，忽略该行的数据
     *
     * @param row 行数据
     * @return 解析后的行数据对象，行数据错误时返回null
     */
    private static SysUser convertRowToData(Row row){
        SysUser resultData = new SysUser();

        Cell cell;
        int cellNum = 0;
        // 获取用户名
        cell = row.getCell(cellNum++);
        String userName = convertCellValueToString(cell);
        resultData.setUserName(userName);
        // 获取姓名
        cell = row.getCell(cellNum++);
        String trueName = convertCellValueToString(cell);
        resultData.setTrueName(trueName);
        //获取密码
        cell = row.getCell(cellNum++);
        String password = convertCellValueToString(cell);
        resultData.setPassword(password);
        // 获取电子邮箱
        cell = row.getCell(cellNum++);
        String email = convertCellValueToString(cell);
        resultData.setEmail(email);
        // 获取电话
        cell = row.getCell(cellNum++);
        String phoneNumber = convertCellValueToString(cell);
        resultData.setPhonenumber(phoneNumber);
        // 获取性别
        cell = row.getCell(cellNum++);
        String sex = convertCellValueToString(cell);
        resultData.setSex(sex);
        // 获取账号状态
        cell = row.getCell(cellNum++);
        String status = convertCellValueToString(cell);
        resultData.setStatus(status);
        // 获取备注
        cell = row.getCell(cellNum++);
        String remark = convertCellValueToString(cell);
        resultData.setRemark(remark);

        return resultData;
    }
}